﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
using MoreLinq;

namespace NimbleTextKeygen
{
    public static class IOUtils
    {
        public static void EnsurePathExists(string sourcePath)
        {
            if (!Directory.Exists(sourcePath))
            {
                Directory.CreateDirectory(sourcePath);
            }
        }
        internal static bool CheckActivationCode(string activationCode, string uniqueCode)
        {
            return IOUtils.CheckActivationCode(activationCode, AssemblyAttributes.ProductName, uniqueCode, AssemblyAttributes.MachineName(), AssemblyAttributes.ProductID);
        }
        internal static bool CheckActivationCode(string activationCode, string productName, string uniqueCode, string machineName, int productID)
        {
            bool flag = activationCode == IOUtils.CreateActivationCode(productName, uniqueCode ?? string.Empty, machineName, productID);
            if (!flag)
            {
                flag = activationCode == IOUtils.CreateActivationCode_Deprecated(productName, uniqueCode, machineName, productID);
            }
            return flag;
        }

        internal static bool CheckLicense(Settings settings)
        {
            return IOUtils.CheckActivationCode(settings.ActivationCode, settings.UniqueCode);
        }

        internal static string GenerateUniqueCode()
        {
            var chars = new List<string>();
            for (char i = 'a'; i < 'z'; i++)
            {
                chars.Add(i.ToString());
            }
            for (char i = 'A'; i < 'Z'; i++)
            {
                chars.Add(i.ToString());
            }
            var numbers = new List<int>() {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};

            return
                $"{chars.Shuffle().Take(4).MergeAsString()}{numbers.Shuffle().Take(4).MergeAsString()}{chars.Shuffle().Take(4).MergeAsString()}{numbers.Shuffle().Take(4).MergeAsString()}";
        }

        private static string MergeAsString<T>(this IEnumerable<T> source)
        {
            var sb = new StringBuilder();
            foreach (var item in source)
            {
                sb.Append(item.ToString());
            }
            return sb.ToString();
        }

        internal static string CreateActivationCode(string productName, string uniqueCode, string machineName, int productID)
        {
            string str = "141264756876943918358326";
            return IOUtils.GetHashCodeCryptographic(string.Concat(string.Concat(string.Concat(string.Concat(string.Concat("", productName.ToLowerInvariant(), "_"), uniqueCode.Replace(" ", "").ToLowerInvariant(), "_"), machineName.Replace("_", "").ToLowerInvariant(), "_"), productID.ToString(), "_"), str)).ToLowerInvariant();
        }

        internal static string CreateActivationCode_Deprecated(string productName, string uniqueCode, string machineName, int productID)
        {
            string str = "141264756876943918358326";
            return IOUtils.GetHashCodeCryptographic(string.Concat(string.Concat(string.Concat(string.Concat(string.Concat("", productName, "_"), uniqueCode, "_"), machineName, "_"), productID.ToString(), "_"), str));
        }

        public static string GetHashCodeCryptographic(string input)
        {
            byte[] numArray = (new MD5CryptoServiceProvider()).ComputeHash(Encoding.Unicode.GetBytes(input.ToCharArray()));
            char[] chrArray = new char[Convert.ToInt32(Math.Ceiling((double)((int)numArray.Length) / 3) * 4)];
            Convert.ToBase64CharArray(numArray, 0, (int)numArray.Length, chrArray, 0);
            return new string(chrArray);
        }

        internal static HashSet<string> LoadRecentFiles()
        {
            string str = Path.Combine(Resources.GetSettingsPath(), "recentFiles.xml");
            HashSet<string> strs = new HashSet<string>();
            if (!File.Exists(str))
            {
                strs = new HashSet<string>();
            }
            else
            {
                string[] strArrays = (string[])Persister.LoadObjectFromXMLFile(str, typeof(string[]));
                if (strArrays != null)
                {
                    string[] strArrays1 = strArrays;
                    for (int i = 0; i < (int)strArrays1.Length; i++)
                    {
                        strs.Add(strArrays1[i]);
                    }
                }
            }
            return strs;
        }
        internal static void SaveSettings(Settings settings)
        {
            Settings settings2 = Persister.Clone<Settings>(settings);
            string fileName = Path.Combine(Resources.GetSettingsPath(), "settings.xml");
            if (!IOUtils.CheckLicense(settings))
            {
                settings2.Snippets = null;
            }
            Persister.SaveObjectToXmlFile(fileName, settings2);
        }

        internal static (Settings settings,Settings defaultSettings) LoadSettingsFromConfig()
        {
            Settings settings = null;
            Settings defaultSettings = Defaults.GetDefaultSettings();
            try
            {
                settings = (Settings)Persister.LoadObjectFromXMLFile(Path.Combine(Resources.GetSettingsPath(), "settings.xml"), typeof(Settings));
            }
            catch (FileNotFoundException fileNotFoundException)
            {
                Log.WriteLine("File Not Found while loading settings file, {0}", new object[] { Path.Combine(Resources.GetSettingsPath(), "settings.xml") });
                settings = defaultSettings;
            }
            if (settings == null)
            {
                settings = defaultSettings;
            }

            return (settings,defaultSettings);
        }
        internal static Settings LoadSettings()
        {
            var (settings, defaultSettings) = LoadSettingsFromConfig();
            if (settings.Theme == null)
            {
                settings.Theme = defaultSettings.Theme;
            }
            if (!settings.TrimFields.HasValue)
            {
                settings.TrimFields = defaultSettings.TrimFields;
            }
            if (!settings.PinAutoPreview.HasValue)
            {
                settings.PinAutoPreview = defaultSettings.PinAutoPreview;
            }
            if (!settings.OutputNewLineAfterEachRow.HasValue)
            {
                settings.OutputNewLineAfterEachRow = defaultSettings.OutputNewLineAfterEachRow;
            }
            if (!settings.IgnoreEmptyRows.HasValue)
            {
                settings.IgnoreEmptyRows = defaultSettings.IgnoreEmptyRows;
            }
            if (settings.DataSortSettings == null)
            {
                settings.DataSortSettings = new SortSettings();
            }
            if (settings.ResultSortSettings == null)
            {
                settings.ResultSortSettings = new SortSettings();
            }
            if (!settings.NormalizeToUnixLineEndings.HasValue)
            {
                settings.NormalizeToUnixLineEndings = defaultSettings.NormalizeToUnixLineEndings;
            }
            if (settings.Version == null)
            {
                settings.Version = "2.9.1.36018";
            }
            if (!settings.WindowState.HasValue)
            {
                settings.WindowState = defaultSettings.WindowState;
                settings.WindowPosition = defaultSettings.WindowPosition;
            }
            if (settings.Snippets == null)
            {
                settings.Snippets = Defaults.GetDefaultSnippets().ToList<Snippet>();
            }
            IOUtils.MergeSnippets(settings.Version, settings.Snippets, Defaults.GetDefaultSnippets().ToList<Snippet>());
            if (!IOUtils.CheckLicense(settings))
            {
                settings.Snippets = Defaults.GetDefaultSnippets().ToList<Snippet>();
                settings.PinShowWhereClause = true;
                settings.ShowWhereClause = false;
            }
            return settings;
        }

        internal static void MergeSnippets(string version, List<Snippet> currentSnippets, List<Snippet> defaultSnippets)
        {
            AssemblyVersion assemblyVersion = new AssemblyVersion(version);
            foreach (Snippet defaultSnippet in defaultSnippets)
            {
                if ((new AssemblyVersion(defaultSnippet.VersionUpdated)).CompareTo(assemblyVersion) <= 0)
                {
                    continue;
                }
                if (currentSnippets.Any<Snippet>((Snippet s) => s.Name == defaultSnippet.Name))
                {
                    currentSnippets.Remove(currentSnippets.First<Snippet>((Snippet s) => s.Name == defaultSnippet.Name));
                }
                currentSnippets.Add(defaultSnippet);
            }
        }
    }
}
